#pragma once

#include "common/Strings.h"
#include "crypto/md2.h"
#include "crypto/md4.h"
#include "crypto/md5.h"
#include "crypto/sha1.h"
#include "crypto/sha224.h"
#include "crypto/sha256.h"
#include "crypto/sha384.h"
#include "crypto/sha512.h"
#include "crypto/ripemd160.h"
#include "crypto/hmac.h"
#include <assert.h>


inline void crypto_test()
{
    {
        unsigned char r[CMD2::OUTPUT_SIZE] = {};
        CMD2 m;
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);
        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "d4541250b586296fcce5dea4463ae17f");
    }
    
    {
        unsigned char r[CMD4::OUTPUT_SIZE] = {};
        CMD4 m;
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);
        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "585028aa0f794af812ee3be8804eb14a");
    }
    
    {
        unsigned char r[CMD5::OUTPUT_SIZE] = {};
        CMD5 m;
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);
        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "e10adc3949ba59abbe56e057f20f883e");
    }

    {
        unsigned char r[CSHA1::OUTPUT_SIZE] = {};
        CSHA1 m;
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);
        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "7c4a8d09ca3762af61e59520943dc26494f8941b");
    }

	{
		unsigned char r[CSHA224::OUTPUT_SIZE] = {};
		CSHA224 m;
		m.Write((uint8_t*)"123", 3);
		m.Write((uint8_t*)"456", 3);
		m.Finalize(r);
		auto hex = Strings::hex_to_string(r, sizeof(r));
		assert(hex == "f8cdb04495ded47615258f9dc6a3f4707fd2405434fefc3cbf4ef4e6");
	}

    {
        unsigned char r[CSHA256::OUTPUT_SIZE] = {};
        CSHA256 m;
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);
        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92");
    }

	{
		unsigned char r[CSHA384::OUTPUT_SIZE] = {};
		CSHA384 m;
		m.Write((uint8_t*)"123", 3);
		m.Write((uint8_t*)"456", 3);
		m.Finalize(r);
		auto hex = Strings::hex_to_string(r, sizeof(r));
		assert(hex == "0a989ebc4a77b56a6e2bb7b19d995d185ce44090c13e2984b7ecc6d446d4b61ea9991b76a4c2f04b1b4d244841449454");
	}

    {
        unsigned char r[CSHA512::OUTPUT_SIZE] = {};
        CSHA512 m;
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);
        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413");
    }

    //////////////////////////////////////////////////////////////////////////
    // HMAC

	{
		uint8_t r[CHMAC<CSHA224>::OUTPUT_SIZE] = {};
		CHMAC<CSHA224> m((uint8_t*)"key", 3);
		m.Write((uint8_t*)"123", 3);
		m.Write((uint8_t*)"456", 3);
		m.Finalize(r);

		auto hex = Strings::hex_to_string(r, sizeof(r));
		assert(hex == "1514bc9965918aa1925b9ea4b598cb66d5fc33338fd775b0c1daecea");
	}

    {
        uint8_t r[CHMAC<CSHA256>::OUTPUT_SIZE] = {};
        CHMAC<CSHA256> m((uint8_t*)"key", 3);
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);

        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "4df81f55d708ae1720d5f65ef42f3475dc168fa23fde424ac5944f87c309b05f");
    }


	{
		uint8_t r[CHMAC<CSHA384>::OUTPUT_SIZE] = {};
		CHMAC<CSHA384> m((uint8_t*)"key", 3);
		m.Write((uint8_t*)"123", 3);
		m.Write((uint8_t*)"456", 3);
		m.Finalize(r);

		auto hex = Strings::hex_to_string(r, sizeof(r));
		assert(hex == "27d471b4ba3ed3d53920336eef1ccde82ee1b1f6c65f1f81cb3851b3b17033f76157465404d6652fedbeecf77b975529");
	}

    {
        uint8_t r[CHMAC<CSHA512>::OUTPUT_SIZE] = {};
        CHMAC<CSHA512> m((uint8_t*)"key", 3);
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);

        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "cc2f51259b61903f6b50ea2cc3653340f1e8c0ae780c927bc1c7f09dcd1d606f7cb3347117f75fa19d9f760f4d538709a969c11036d194b972bf3232f34f30a8");
    }

    {
        uint8_t r[CHMAC<CSHA1>::OUTPUT_SIZE] = {};
        CHMAC<CSHA1> m((uint8_t*)"key", 3);
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);

        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "4fc32f51f214211618a9598893823519b829ee74");
    }

    {
        uint8_t r[CHMAC<CMD4>::OUTPUT_SIZE] = {};
        CHMAC<CMD4> m((uint8_t*)"key", 3);
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);

        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "96ecc5b3651afafb3fff608d4cea5e18");
    }

    {
        uint8_t r[CHMAC<CMD5>::OUTPUT_SIZE] = {};
        CHMAC<CMD5> m((uint8_t*)"key", 3);
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);

        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "0abf6bacd23c55fa6ab14eb44a7f5720");
    }

    {
        uint8_t r[CHMAC<CMD2>::OUTPUT_SIZE] = {};
        CHMAC<CMD2> m((uint8_t*)"key", 3);
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);

        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "c75f908aeaf9ef173ff5d14edca72d19");
    }

    {
        uint8_t r[CHMAC<CRIPEMD160>::OUTPUT_SIZE] = {};
        CHMAC<CRIPEMD160> m((uint8_t*)"key", 3);
        m.Write((uint8_t*)"123", 3);
        m.Write((uint8_t*)"456", 3);
        m.Finalize(r);

        auto hex = Strings::hex_to_string(r, sizeof(r));
        assert(hex == "519a02e2aed87b8ee3e392a600b75a33455160e6");
    }

}